
#include <cstdio>
#include <BPainter>
#include <BRender>
#include <BViewer>
#include <BCone>
#include <BCube>
#include <BReadWrite>
#include <BImage>

#include <BCube>
#include <BSphere>
#include <BCylinder>
#include <BCapsule>
#include <BScene>

#include "TerrainSampleHandler.h"

TerrainSampleHandler::TerrainSampleHandler()
{
	_group = new BGroup();
	
	//if (BCube* cube = new BCube(1, 10))
	//{
	//	cube->setName("cube");
	//	cube->setColor(150, 120, 100);
	//	for (int k = 0; k < 5; k++)
	//	{
	//		for (int i = 0; i < 5; i++)
	//		{
	//			for (int j = 0; j < 5; j++)
	//			{
	//				BString name("cube");
	//				name << '-' << k << '-' << i << '-' << j;
	//				BBody* body = new BBody(name);
	//				body->setMass(1);
	//				body->insertShape(cube);
	//				body->setPosition((BReal)2 * i, (BReal)2 * j, 24 + (BReal)2 * k);
	//				_group->insert(body);
	//			}
	//		}
	//	}
	//}

	if (BSphere* sphere = new BSphere(1))
	{
		sphere->setName("sphere");
		sphere->setColor(120, 150, 100);
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < 10; j++)
			{
				BString name("sphere");
				name << '-' << i << '-' << j;
				BBody* body = new BBody(name);
				body->setPosition((BReal)2 * i, (BReal)2 * j, 50);
				body->setMass(1);
				body->insertShape(sphere);
				_group->insert(body);
			}
		}
	}
	
	//if (BCylinder* cylinder = new BCylinder(1, 2, 24, 6, 6))
	//{
	//	cylinder->setColor(220, 150, 100);
	//	for (int i = 0; i < 10; i++)
	//	{
	//		for (int j = 0; j < 10; j++)
	//		{
	//			BString name("cylinder");
	//			name << '-' << i << '-' << j;
	//			BBody* body = new BBody(name);
	//			body->setPosition((BReal)2 * i, (BReal)2 * j, 60);
	//			body->setMass(1);
	//			body->insertShape(cylinder);
	//			_group->insert(body);
	//		}
	//	}
	//}

	BBody* capsulesBody = new BBody("capsules");
	{
		capsulesBody->setPosition(-5, -5, 50);
		capsulesBody->setMass(10);
		BReal height = 1;
		BReal offset = (BReal)10 / 10;
		BVector origin(-5, -5, 0);
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < 10; j++)
			{
				BString name("sphere");
				name << '-' << i << '-' << j;
				BCapsule* capsule = new BCapsule(offset * 0.4, height, 24, 6, 6);
				capsule->setName(name);
				capsule->setColor(220, 100, 100);
				capsule->setPosition(origin + BVector(offset * i, offset * j, 0));
				capsulesBody->insertShape(capsule);
			}
		}
	}
	//_group->insert(capsulesBody);

	_terrainBody = new BBody("terrain");
	{
		BTerrain* terrain = createTerrain("data/terrain/terrain-small.tiff");
		terrain->setCullback(false);
		const BSpace& space = terrain->space();
		_terrainBody->setPosition(BVector(-space.width() / 3, -space.height() / 3, 0));
		_terrainBody->insertShape(terrain);
		//_terrainBody->setMass(10);
	}
	_group->insert(_terrainBody);

}
TerrainSampleHandler::~TerrainSampleHandler()
{

}

BTerrain* TerrainSampleHandler::createTerrain(const BString& fileName)
{
	if (fileName.size())
	{
		BImage* elevationImage = ReadFile<BImage>(fileName);
		if (!elevationImage)
		{
			perror("error : read elevation tif file faild.");
			return 0;
		}

		Format format = elevationImage->format();
		int width = elevationImage->width();
		int height = elevationImage->height();
		int size = width * height;

		BTerrain* terrain = new BTerrain((BReal)width, (BReal)height, width, height);
		terrain->setPolySmooth(true);

		BRealTable& elevation = terrain->elevation();
		const BByteArray* pixels = elevationImage->pixels();
		switch (format)
		{
		case Format_UChar:
			elevation.fill((unsigned char*)pixels->data(), pixels->size());
			break;
		case Format_UShort:
			elevation.fill((unsigned short*)pixels->data(), pixels->size() / 2);
			break;
		case Format_Short:
			elevation.fill((short*)pixels->data(), pixels->size() / 2);
			break;
		case  Format_UInt:
			elevation.fill((unsigned int*)pixels->data(), pixels->size() / 4);
			break;
		case  Format_Int:
			elevation.fill((int*)pixels->data(), pixels->size() / 4);
			break;
		case  Format_Float:
			elevation.fill((float*)pixels->data(), pixels->size() / 4);
			break;
		case  Format_Double:
			elevation.fill((double*)pixels->data(), pixels->size() / 8);
			break;
		default:
			break;
		}
		elevation.reverse(Orientation_Vertical);
		for (int i = 0; i < elevation.size(); i++)
		{
			elevation(i) *= (BReal)0.01;
		}
		terrain->setElevation(elevation);
		terrain->smooth();

		BString textureFileName = fileName;
		textureFileName -= ".tiff";
		textureFileName -= ".tif";
		textureFileName += ".jpg";
		BImage* image = ReadFile<BImage>(textureFileName);
		if (image)
		{
			image->setBlend(BTexture::Blend_Modulate);
			terrain->setTexture(image);
		}

		return terrain;
	}
	return 0;
}

void TerrainSampleHandler::attached(BViewer* viewer)
{
	viewer->scene()->insert(_group);
}
void TerrainSampleHandler::detached(BViewer* viewer)
{
	viewer->scene()->remove(_group);
}

void TerrainSampleHandler::paint(BPainter& painter)
{
	BViewer* viewer = this->viewer();

}
void TerrainSampleHandler::render(BRender& render)
{
	render.setLighting(false);
	render.setDepthTest(false);
	render.setLineSmooth(true);
	render.setLineWidth(1);
	
}
